#include "trim_cmd.h"
#include "trim.h"
#include "util_cmd.h"
#include "util_str.h"
#include "uart_nuvoton.h"
#include "stdio.h"
#include "string.h"

struct __TrimCmdManager {
	uint8_t critical : 1;
	uint8_t reversed : 7;
	
	uint16_t nopNum;
	
	uint8_t *byteCache;
	uint16_t *halfwordCache;
	uint32_t *wordCache;
};

static struct __TrimCmdManager *sTrimCmdManager = NULL;

static char *sCmdTrim = "trim";
static char *sPar17bit = "17bit";
static char *sPar16bit = "16bit";
static char *sParBurn = "burn";

static void par17bitFun(uint8_t *data)
{
	uint16_t ana;
	
	ana = StrChar2Hex5ch((char *)data, 0, TRIM_CMD_WORDCACHE_SZIE, sTrimCmdManager->wordCache, TRIM_CMD_HALFCACHE_SIZE);
	TrimSPISend17BitsArray(sTrimCmdManager->wordCache, ana / 5, 64);
}

static void parBurnFunc(uint8_t *data)
{
	int16_t index;
	uint8_t bitNum;
	uint32_t code;
	
	index = StrGetNextNotSpace((char *)data);
	if (index == -1) {
		UartPutsPDMA(UART_COM1, "burn: No param\r\n");
		return;
	}
	
	bitNum = StrGetDec((char *)&data[index], 0, 3);
	code = StrGetHex((char *)&data[index+3], 0, 8);
	UartPrintfPDMA(UART_COM1, "bitNum = %d, trim code = 0x%08X\r\n", bitNum, code);
	TrimWrite(code, bitNum);
	UartPutsPDMA(UART_COM1, "trim done!\r\n");
}


static void par16bitFunc(uint8_t *data)
{
	uint16_t ana;
	
	ana = StrChar2Hex((char *)data, 0, TRIM_CMD_HALFCACHE_SIZE, sTrimCmdManager->halfwordCache, TRIM_CMD_HALFCACHE_SIZE);
	TrimSPISendHalfwordArray(sTrimCmdManager->halfwordCache, ana / 4, sTrimCmdManager->nopNum);
}

static void cmdTrimCallback(CmdParamTypeDef *param)
{
	uint8_t *receiveArray = UartGetRxBuffer(UART_COM1);
	
	if (param == NULL) {
		UartPrintf(UART_COM1, "Trim state:\r\n");
		UartPrintfPDMA(UART_COM1, "critical = %d\r\n", sTrimCmdManager->critical);
		return;
	}
	
	if (strcmp(param->name, sPar17bit) == 0) {
		par17bitFun(&receiveArray[param->index]);
	}
	else if (strcmp(param->name, sPar16bit) == 0) {
		par16bitFunc(&receiveArray[param->index]);
	}
    else if (strcmp(param->name, sParBurn) == 0) {
		parBurnFunc(&receiveArray[param->index]);
	}
}

void TrimCmdInit(void)
{
	static struct __TrimCmdManager manager;
	static uint32_t wordCache[TRIM_CMD_WORDCACHE_SZIE];
	static uint16_t halfwordCache[TRIM_CMD_HALFCACHE_SIZE];
	
	if (sTrimCmdManager == NULL) {
		manager.critical = 0;
		
		manager.nopNum = 64;
		
		manager.byteCache = NULL;
		manager.halfwordCache = halfwordCache;
		manager.wordCache = wordCache;
		
		sTrimCmdManager = &manager;
	}
	CmdAppend(sCmdTrim, cmdTrimCallback);
	CmdAppendParam(sCmdTrim, sPar17bit);
	CmdAppendParam(sCmdTrim, sPar16bit);
    CmdAppendParam(sCmdTrim, sParBurn);
}
